const express = require('express');
const { Web3 } = require('web3');
const router = express.Router();
const { authenticateToken } = require('./auth');
const db = require('../database/connection');

// Initialize Web3 connection to BSC
const web3 = new Web3(process.env.BSC_RPC_URL || 'https://bsc-dataseed1.binance.org/');

// Get system settings
async function getSystemSetting(key) {
  const setting = await db.query(
    'SELECT setting_value FROM system_settings WHERE setting_key = ?',
    [key]
  );
  return setting.length > 0 ? setting[0].setting_value : null;
}

// Create transaction record
async function createTransaction(userId, transactionData) {
  const { hash, type, amount, fromAddress, toAddress, blockNumber, blockTimestamp } = transactionData;

  return await db.query(
    `INSERT INTO transactions
     (user_id, transaction_hash, transaction_type, amount, from_address, to_address, block_number, block_timestamp, status)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [userId, hash, type, amount, fromAddress, toAddress, blockNumber, blockTimestamp, 'confirmed']
  );
}

// Update user balance
async function updateBalance(userId, availableChange, stakedChange = 0) {
  return await db.query(
    `UPDATE user_balances
     SET available_balance = available_balance + ?,
         staked_balance = staked_balance + ?,
         updated_at = CURRENT_TIMESTAMP
     WHERE user_id = ?`,
    [availableChange, stakedChange, userId]
  );
}

// Verify BSC transaction
async function verifyTransaction(txHash) {
  try {
    const transaction = await web3.eth.getTransaction(txHash);
    const receipt = await web3.eth.getTransactionReceipt(txHash);

    if (!transaction || !receipt) {
      return null;
    }

    return {
      transaction,
      receipt,
      status: receipt.status === true ? 'confirmed' : 'failed',
      blockNumber: receipt.blockNumber,
      gasUsed: receipt.gasUsed,
      logs: receipt.logs
    };
  } catch (error) {
    console.error('Transaction verification error:', error);
    return null;
  }
}

// Record deposit transaction
router.post('/deposit', authenticateToken, async (req, res) => {
  try {
    const { txHash, amount } = req.body;
    const userId = req.user.userId;

    if (!txHash || !amount) {
      return res.status(400).json({ error: 'Transaction hash and amount are required' });
    }

    // Check if transaction already exists
    const existingTx = await db.query(
      'SELECT id FROM transactions WHERE transaction_hash = ?',
      [txHash]
    );

    if (existingTx.length > 0) {
      return res.status(409).json({ error: 'Transaction already processed' });
    }

    // Verify transaction on BSC
    const txData = await verifyTransaction(txHash);
    if (!txData) {
      return res.status(400).json({ error: 'Invalid transaction' });
    }

    if (txData.status !== 'confirmed') {
      return res.status(400).json({ error: 'Transaction failed' });
    }

    // Get system addresses
    const publicWalletAddress = await getSystemSetting('public_wallet_address');
    const godTokenContractAddress = await getSystemSetting('god_token_contract_address');

    if (!publicWalletAddress || !godTokenContractAddress) {
      return res.status(500).json({ error: 'System configuration missing' });
    }

    // Get user wallet address
    const user = await db.query('SELECT wallet_address FROM users WHERE id = ?', [userId]);
    if (user.length === 0) {
      return res.status(404).json({ error: 'User not found' });
    }

    // Verify transaction details (simplified - in production, verify token transfer logs)
    if (txData.transaction.to.toLowerCase() !== publicWalletAddress.toLowerCase()) {
      return res.status(400).json({ error: 'Invalid destination address' });
    }

    // Process deposit in a transaction
    await db.transaction(async (connection) => {
      // Record transaction
      await connection.execute(
        `INSERT INTO transactions
         (user_id, transaction_hash, transaction_type, amount, from_address, to_address, block_number, status)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          userId,
          txHash,
          'deposit',
          amount,
          txData.transaction.from,
          txData.transaction.to,
          txData.blockNumber,
          'confirmed'
        ]
      );

      // Update user balance
      await connection.execute(
        `UPDATE user_balances
         SET available_balance = available_balance + ?, updated_at = CURRENT_TIMESTAMP
         WHERE user_id = ?`,
        [amount, userId]
      );

      // Check for referral rewards
      const referralData = await connection.execute(
        'SELECT referred_by FROM users WHERE id = ?',
        [userId]
      );

      if (referralData[0] && referralData[0].referred_by) {
        const referrer = await connection.execute(
          'SELECT id FROM users WHERE referral_code = ?',
          [referralData[0].referred_by]
        );

        if (referrer[0]) {
          const referralRewardPercentage = parseFloat(await getSystemSetting('referral_reward_percentage')) || 0.10;
          const rewardAmount = amount * referralRewardPercentage;

          // Record referral reward
          await connection.execute(
            `INSERT INTO referral_rewards (referrer_id, referred_user_id, reward_amount, reward_type)
             VALUES (?, ?, ?, ?)`,
            [referrer[0].id, userId, rewardAmount, 'deposit_bonus']
          );

          // Update referrer's balance
          await connection.execute(
            `UPDATE user_balances
             SET available_balance = available_balance + ?, total_earned = total_earned + ?, updated_at = CURRENT_TIMESTAMP
             WHERE user_id = ?`,
            [rewardAmount, rewardAmount, referrer[0].id]
          );
        }
      }
    });

    res.json({
      message: 'Deposit processed successfully',
      amount,
      txHash
    });

  } catch (error) {
    console.error('Deposit error:', error);
    res.status(500).json({ error: 'Failed to process deposit' });
  }
});

// Request withdrawal
router.post('/withdraw', authenticateToken, async (req, res) => {
  try {
    const { amount, toAddress } = req.body;
    const userId = req.user.userId;

    if (!amount || !toAddress) {
      return res.status(400).json({ error: 'Amount and destination address are required' });
    }

    if (amount <= 0) {
      return res.status(400).json({ error: 'Amount must be greater than 0' });
    }

    // Validate address format
    if (!/^0x[a-fA-F0-9]{40}$/.test(toAddress)) {
      return res.status(400).json({ error: 'Invalid destination address format' });
    }

    // Check user balance
    const balance = await db.query(
      'SELECT available_balance FROM user_balances WHERE user_id = ?',
      [userId]
    );

    if (balance.length === 0) {
      return res.status(404).json({ error: 'User balance not found' });
    }

    if (parseFloat(balance[0].available_balance) < parseFloat(amount)) {
      return res.status(400).json({ error: 'Insufficient balance' });
    }

    // Create withdrawal request (in production, this would trigger an actual transaction)
    const withdrawalId = await db.transaction(async (connection) => {
      // Deduct from user balance
      await connection.execute(
        `UPDATE user_balances
         SET available_balance = available_balance - ?, updated_at = CURRENT_TIMESTAMP
         WHERE user_id = ?`,
        [amount, userId]
      );

      // Create withdrawal transaction record
      const [result] = await connection.execute(
        `INSERT INTO transactions
         (user_id, transaction_type, amount, to_address, status)
         VALUES (?, ?, ?, ?, ?)`,
        [userId, 'withdrawal', amount, toAddress, 'pending']
      );

      return result.insertId;
    });

    res.json({
      message: 'Withdrawal request created',
      withdrawalId,
      amount,
      toAddress
    });

  } catch (error) {
    console.error('Withdrawal error:', error);
    res.status(500).json({ error: 'Failed to create withdrawal request' });
  }
});

// Get transaction status
router.get('/status/:txHash', authenticateToken, async (req, res) => {
  try {
    const { txHash } = req.params;
    const userId = req.user.userId;

    const transaction = await db.query(
      `SELECT transaction_hash, transaction_type, amount, status, created_at
       FROM transactions
       WHERE transaction_hash = ? AND user_id = ?`,
      [txHash, userId]
    );

    if (transaction.length === 0) {
      return res.status(404).json({ error: 'Transaction not found' });
    }

    res.json(transaction[0]);

  } catch (error) {
    console.error('Transaction status error:', error);
    res.status(500).json({ error: 'Failed to fetch transaction status' });
  }
});

module.exports = router;